<template>
	<view class="uni-card" 
		:class="{'uni-card--full': isFull, 'uni-card--shadow': !isShot && isShadow, 'uni-card--border': border}"
		:style="[{
			margin: isFull ? 0 : margin, 
			padding: spacing, overflow,
			boxShadow: !isShot && isShadow ? shadow : '', 
		}, bgSrc ? {background: `url('${bgSrc}')`} : {}]"
	>
		<!-- 封面 -->
		<slot name="cover">
			<view v-if="cover" class="uni-card__cover">
				<image class="uni-card__cover-image" mode="widthFix" :src="cover" @click.stop="onClick('cover')"></image>
			</view>
		</slot>
		<slot name="title">
			<view class="uni-card__header" :style="[{borderBottomWidth: (showHeaderLine() ? 1 : 0) + 'px'}]" @click.stop="onClick('title')">
				<!-- 卡片标题 -->
				<slot name="main">
					<view class="uni-card__header-box" @click="onClick('main')">
						<view v-if="thumbnail" class="uni-card__header-avatar">
							<image class="uni-card__header-avatar-image" :style="[thumbnailSize ? {width: thumbnailSize + 'px', height: thumbnailSize + 'px'} : {}]" :src="thumbnail" mode="aspectFit" @click.stop="onClick('thumbnail')"/>
						</view>
						<IconFont v-else-if="thumbnailIcon" :type="thumbnailIcon" :size="thumbnailSize" :color="thumbnailColor"/>
						<view class="uni-card__header-content">
							<div style="display: flex;">
								<text v-if="redxing" class="is-required">*</text>
								<text class="uni-card__header-content-title uni-ellipsis" :style="[{color: titleColor}, titleStyle]">{{lang(title)}}</text>
								<IconFont v-if="parseInt(genderValue)" :type="`xb-${parseInt(genderValue) === 1 ? 'nan' : 'nv'}`" size="10" :color="parseInt(genderValue) === 1 ?'#1296db' : '#d4237a'"/>
							</div>
							<slot name="subTitle">
								<text v-if="subTitle" class="uni-card__header-content-subtitle uni-ellipsis" :style="[{color: subTitleColor}]">{{lang(subTitle)}}</text>
							</slot>
						</view>
					</view>
				</slot>
				<slot name="extra">
					<view class="uni-card__header-extra" @click.stop="onClick('extra')">
						<CaPhone v-if="extraPhone" :phone="extraPhone" :type="phoneType"/>
						<IconFont v-else-if="extraClose" :type="getExtraIcon" :rotate="extraRotate" :size="extraSize"/>
						<div v-if="extraSpread">
							<IconFont v-if="spreadIcon" :type="spreadIcon" :rotate="extraRotate - (isSpread ? 0 : 90)" :size="extraSize"/>
							<text v-else class="uni-card__header-extra-text">{{lang(isSpread ? spreadText0 : spreadText1)}}</text>
						</div>
						<text v-else class="uni-card__header-extra-text">{{lang(extra)}}</text>
					</view>
				</slot>
			</view>
		</slot>
		<!-- 卡片内容 -->
		<view v-if="isSpread" class="uni-card__content" :style="[{padding}]" @click.stop="onClick('content')">
			<slot></slot>
		</view>
		<!-- 收起状态下显示的内容 -->
		<slot v-else name="unspread"></slot>
		<view class="uni-card__actions" @click.stop="onClick('actions')">
			<slot name="actions"></slot>
		</view>
	</view>
</template>

<script>
	/**
	 * Card 卡片
	 * @description 卡片视图组件
	 * @tutorial https://ext.dcloud.net.cn/plugin?id=22
	 * @property {String} title 标题文字
	 * @property {String} subTitle 副标题
	 * @property {Number} padding 内容内边距
	 * @property {Number} margin 卡片外边距
	 * @property {Number} spacing 卡片内边距
	 * @property {String} extra 标题额外信息
	 * @property {String} cover 封面图（本地路径需要引入）
	 * @property {String} thumbnail 标题左侧缩略图
	 * @property {Boolean} is-full = [true | false] 卡片内容是否通栏，为 true 时将去除padding值
	 * @property {Boolean} is-shadow = [true | false] 卡片内容是否开启阴影
	 * @property {String} shadow 卡片阴影
	 * @property {Boolean} border 卡片边框
	 * @event {Function} click 点击 Card 触发事件
	 */
	
	import base from '@/components/index.vue'
	
	export default {
		extends: base,
		name: 'UniCard',
		emits: ['click', 'spread', 'extra', 'title'],
		props: {
			title: {
				type: String,
				default: ''
			},
			subTitle: {
				type: String,
				default: ''
			},
			padding: {
				type: String,
				default: '10px'
			},
			margin: {
				type: String,
				default: '15px'
			},
			spacing: {
				type: String,
				default: '0 10px'
			},
			extra: {
				type: String,
				default: ''
			},
			cover: {
				type: String,
				default: ''
			},
			// 点击是否显示大图
			coverBig: Boolean, 
			thumbnail: {
				type: String,
				default: ''
			},
			thumbnailIcon: String,
			thumbnailColor: {
				type: String,
				default: '#8A8A8A'
			},
			thumbnailSize: {
				type: [String, Number],
				default: 40
			},
			// 点击是否显示大图
			thumbnailBig: Boolean, 
			isFull: { // 内容区域是否通栏
				type: Boolean,
				default: false
			},
			isShadow: { // 是否开启阴影
				type: Boolean,
				default: true
			},
			isShot: { // 是否裁剪模式。截图模式下需控制一些设置。主要是不支持shadow设置
				type: Boolean,
				default: false
			},
			shadow: {
				type: String,
				default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)'
			},
			border: {
				type: Boolean,
				default: true
			},
			// 默认的展开值。该value仅用于控制卡片是否展开
			value: {
				type: Boolean,
				default: true
			},
			// 点击展开/收起效果的范围。字符串的话，用,隔开。会有回调事件$emit('spread')，回调展开/收起的结果
			openSpread: {
				type: [Array, String],
				default: () => {
					return [
						// 'cover',
						// 'title',
						// 'extra',
						// 'content',
						// 'actions'
					]
				}
			},
			// 是否隐藏Header的底部线条。isSpread为false时也自动隐藏
			hideHeaderLine: Boolean,
			// 右上角是展开收起，可以是带-的字符串，比如“收起/展开”，如果没有/表示是图标，收起时旋转90度
			extraSpread: [Boolean, String],
			// 右上角是关闭图标，可以是字符串，表示自定义的关闭图标
			extraClose: [Boolean, String],
			// 右上角是电话号码。优先级最高
			extraPhone: [String, Number],
			// 右上角是图标时旋转多少度
			extraRotate: {
				type: Number,
				default: 0
			},
			// 右上角图标或文字时的大小
			extraSize: {
				type: [Number, String],
				default: 12
			},
			// 电话呼出类型。0：本地直拨；1：云电话呼出；2：选择以上两种
			phoneType: [String, Number],
			// 如果大于0的值，将会显示性别。0：不显示；1：男；2：女
			genderValue: [Number, String],
			// 标题颜色
			titleColor: String,
			// 副标题颜色
			subTitleColor: String,
			/**
			 * 溢出设置
			 * visible：内容不能被裁减并且可能渲染到边距盒（padding）的外部
			 * hidden：如果需要，内容将被裁减以适应边距（padding）盒。不提供滚动条，也不支持允许用户滚动（例如通过拖拽或者使用滚轮）。内容可以以编程的方式滚动（例如，通过设置 scrollLeft 等属性的值或 scrollTo() 方法）, 因此该元素仍然是一个滚动的容器。
			 * clip：类似于 hidden，内容将以元素的边距（padding）盒进行裁剪。clip 和 hidden 之间的区别是 clip 关键字禁止所有滚动，包括以编程方式的滚动。该盒子不是一个滚动的容器，并且不会启动新的格式化上下文。如果你希望开启一个新的格式化上下文，你可以使用 display: flow-root 来这样做。
			 * scroll：如果需要，内容将被裁减以适应边距（padding）盒。无论是否实际裁剪了任何内容，浏览器总是显示滚动条，以防止滚动条在内容改变时出现或者消失。打印机可能会打印溢出的内容。
			 * auto：取决于用户代理。如果内容适应边距（padding）盒，它看起来与 visible 相同，但是仍然建立了一个新的块级格式化上下文。如果内容溢出，则浏览器提供滚动条。
			 * overlay：行为与 auto 相同，但是滚动条绘制在内容之上，而不是占据空间。
			 */
			overflow: {
				type: String,
				default: 'visible'
			},
			// 背景图
			bgSrc: String,
			// 标题是否带红星
			redxing: Boolean,
			// 标题的样式。多重卡片时可突出标题
			titleStyle: Object
		},
		watch: {
			value(val) {
				this.initial()
			}
		},
		data() {
			return {
				/**
				 * 展开收起的控制。
				 * openSpread和extraSpread都可以让isSpread生效
				 */
				isSpread: this.value === false ? false : true,
				// 只有extraSpread生效，下面三项才有
				spreadText0: '收起',
				spreadText1: '展开',
				spreadIcon: '',
			}
		},
		computed: {
			getExtraIcon() {
				if (typeof(this.extraClose) === 'string') {
					return this.extraClose
				}
				return 'close'
			}
		},
		mounted() {
			this.initial()
		},
		methods: {
			initial() {
				var isSpread
				// 默认都是展开
				if (this.extraSpread) {
					isSpread = true
					if (typeof(this.extraSpread) === 'string') {
						const arr = this.extraSpread.split('/')
						if (arr.length === 1) {
							this.spreadIcon = arr[0]
						} else {
							this.spreadText0 = arr[0]
							this.spreadText1 = arr[1]
						}
					} else {
						this.spreadText0 = '收起'
						this.spreadText1 = '展开'
					}
				}
				if (this.openSpread && this.openSpread.length > 0) {
					isSpread = true
				}
				if (this.value === true) {
					isSpread = true
				} else if (this.value === false) {
					isSpread = false
				}
				this.isSpread = !!isSpread
			},
			
			// 是否显示头部线
			showHeaderLine() {
				const {hideHeaderLine, isSpread, $slots} = this
				if (hideHeaderLine) { // 明确隐藏
					return false
				}
				if ($slots.actions) { // 有底部区域并且中间内容是展开状态，就显示
					if (isSpread) {
						return true
					}
					return false
				}
				if (isSpread) {
					// 展开情况下，不处理
				} else {
					// 如果存在收起区域也显示
					if ($slots.unspread) {
						return true
					}
					// 默认收起状态下就隐藏
					return false
				}
				return true
			},
			
			onClick(type) {
				if (type === 'cover') {
					if (this.cover && this.coverBig) {
						uni.previewImage({
							urls: [this.cover]
						})
						return
					}
				}
				if (type === 'thumbnail') {
					if (this.thumbnail && this.thumbnailBig) {
						uni.previewImage({
							urls: [this.thumbnail]
						})
						return
					}
				}
				if (this.openSpread.indexOf(type) === -1 && !(type === 'extra' && this.extraSpread)) {
					this.$emit('click', type)
					if (type === 'extra') {
						this.$emit('extra')
					} else if (type === 'title') {
						this.$emit('title')
					}
				} else {
					this.isSpread = !this.isSpread
					this.$emit('input', this.isSpread)
					this.$emit('spread', this.isSpread)
				}
			}
		}
	}
</script>

<style lang="scss">
	$uni-border-3: #EBEEF5 !default;
	$uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
	$uni-main-color: #3a3a3a !default;
	$uni-base-color: #6a6a6a !default;
	$uni-secondary-color: #909399 !default;
	$uni-spacing-sm: 8px !default;
	$uni-border-color:$uni-border-3;
	$uni-shadow: $uni-shadow-base;
	$uni-card-title: 15px;
	$uni-cart-title-color:$uni-main-color;
	$uni-card-subtitle: 12px;
	$uni-cart-subtitle-color:$uni-secondary-color;
	$uni-card-spacing: 10px;
	$uni-card-content-color: $uni-base-color;

	.uni-card {
		margin: $uni-card-spacing;
		padding: 0 $uni-spacing-sm;
		border-radius: 4px;
		overflow: hidden;
		font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
		background-color: #fff;
		// flex: 1; // 3.26注释掉该属性

		.uni-card__cover {
			position: relative;
			margin-top: $uni-card-spacing;
			flex-direction: row;
			overflow: hidden;
			border-radius: 4px;
			text-align: center;
			.uni-card__cover-image {
				flex: 1;
				// width: 100%;
				/* #ifndef APP-PLUS */
				vertical-align: middle;
				/* #endif */
			}
		}

		.uni-card__header {
			display: flex;
			border-bottom: 1px $uni-border-color solid;
			flex-direction: row;
			align-items: center;
			padding: $uni-card-spacing;
			overflow: hidden;

			.uni-card__header-box {
				/* #ifndef APP-NVUE */
				display: flex;
				/* #endif */
				flex: 1;
				flex-direction: row;
				align-items: center;
				overflow: hidden;
			}

			.uni-card__header-avatar {
				width: 40px;
				height: 40px;
				overflow: hidden;
				border-radius: 5px;
				margin-right: $uni-card-spacing;
				.uni-card__header-avatar-image {
					flex: 1;
					width: 40px;
					height: 40px;
				}
			}

			.uni-card__header-content {
				/* #ifndef APP-NVUE */
				display: flex;
				/* #endif */
				flex-direction: column;
				justify-content: center;
				flex: 1;
				// height: 40px;
				overflow: hidden;

				.uni-card__header-content-title {
					font-size: $uni-card-title;
					color: $uni-cart-title-color;
					// line-height: 22px;
				}

				.uni-card__header-content-subtitle {
					font-size: $uni-card-subtitle;
					margin-top: 5px;
					color: $uni-cart-subtitle-color;
				}
				
				.is-required {
					// color: $uni-color-error;
					color: #dd524d;
					font-weight: bold;
				}
			}

			.uni-card__header-extra {
				line-height: 12px;

				.uni-card__header-extra-text {
					font-size: 12px;
					color: $uni-cart-subtitle-color;
				}
			}
		}

		.uni-card__content {
			padding: $uni-card-spacing;
			font-size: 14px;
			color: $uni-card-content-color;
			line-height: 22px;
		}

		.uni-card__actions {
			font-size: 12px;
		}
	}

	.uni-card--border {
		border: 1px solid $uni-border-color;
	}

	.uni-card--shadow {
		position: relative;
		/* #ifndef APP-NVUE */
		box-shadow: $uni-shadow;
		/* #endif */
	}

	.uni-card--full {
		margin: 0;
		border-left-width: 0;
		border-left-width: 0;
		border-radius: 0;
	}

	/* #ifndef APP-NVUE */
	.uni-card--full:after {
		border-radius: 0;
	}

	/* #endif */
	.uni-ellipsis {
		/* #ifndef APP-NVUE */
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
		/* #endif */
		/* #ifdef APP-NVUE */
		lines: 1;
		/* #endif */
	}
</style>
